package com.nikmesoft.nmsharekit.helpers;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;

import twitter4j.StatusUpdate;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.User;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;
import twitter4j.conf.Configuration;
import twitter4j.conf.ConfigurationBuilder;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Window;
import android.widget.Toast;
import com.facebook.LoggingBehavior;
import com.facebook.Settings;
import com.nikmesoft.nmsharekit.R;
import com.nikmesoft.nmsharekit.configers.NMSKDevDefine;
import com.nikmesoft.nmsharekit.delegates.NMSKTwitterDialogDelegate;
import com.nikmesoft.nmsharekit.delegates.NMSKTwitterLoginDialogDelegate;
import com.nikmesoft.nmsharekit.objects.NMShareMessage;
import com.nikmesoft.nmsharekit.objects.NMShareMessage.NMShareType;
import com.nikmesoft.nmsharekit.utils.NMSKTwitterSession;
import com.nikmesoft.nmsharekit.views.NMSKTwitterDialog;
import com.nikmesoft.nmsharekit.views.NMSKTwitterLoginDialog;

public class NMSKTwitterHelper implements NMSKTwitterLoginDialogDelegate,
		NMSKTwitterDialogDelegate {
	public static NMSKTwitterHelper instance;
	private Context context;
	private Activity activity;
	private static final String TAG = NMSKTwitterHelper.class.getSimpleName();
	private static Twitter twitter;
	private static RequestToken requestToken;
	private String consumerKey;
	private String secretKey;
	private String callBackURL;
	private ProgressDialog progressDialog;
	private MyHandler mHandler;
	private AccessToken accessToken;
	private NMShareMessage message;

	// share instance
	public static NMSKTwitterHelper sharedInstance(Context context,
			Activity activity) {
		if (instance == null) {
			instance = new NMSKTwitterHelper(context, activity);
		}
		return instance;
	}

	public NMSKTwitterHelper(Context context, Activity activity) {
		super();
		this.context = context;
		this.activity = activity;
		Settings.addLoggingBehavior(LoggingBehavior.INCLUDE_ACCESS_TOKENS);
		this.context = context;
		this.secretKey = NMSKDevDefine.sharedInstance(context, activity)
				.getTwitterSecretKey();
		this.consumerKey = NMSKDevDefine.sharedInstance(context, activity)
				.getTwitterConsumerKey();
		this.callBackURL = NMSKDevDefine.sharedInstance(context, activity)
				.getTwitterCallBack();
		this.progressDialog = new ProgressDialog(context);
		this.progressDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
		this.mHandler = new MyHandler(this);
		this.accessToken = NMSKTwitterSession.getInstance(context)
				.getAccessToken();
		if (accessToken != null) {
			ConfigurationBuilder builder = new ConfigurationBuilder();
			builder.setOAuthConsumerKey(consumerKey);
			builder.setOAuthConsumerSecret(secretKey);
			Configuration configuration = builder.build();
			TwitterFactory factory = new TwitterFactory(configuration);
			twitter = factory.getInstance();
			twitter.setOAuthAccessToken(accessToken);
		}
	}

	public void share(NMShareMessage message) {
		this.message = message;
		Intent shareIntent = new Intent(android.content.Intent.ACTION_SEND);
		if (message.getType() == NMShareType.NMShareTypeStory) {
			shareIntent.setType("image/*");
			shareIntent.putExtra(Intent.EXTRA_STREAM,
					Uri.fromFile(new File(message.getPicture())));
			shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
		} else {
			shareIntent.setType("text/plain");
		}

		shareIntent.setClassName("com.twitter.android",
				"com.twitter.android.PostActivity");

		shareIntent.putExtra(android.content.Intent.EXTRA_TEXT,
				message.getMessage());

		try {
			// open native app
			context.startActivity(shareIntent);
		} catch (ActivityNotFoundException ex) {
			// using Twitter api
			if (!hasAccessToken()) {
				authorize();
			} else {
				// TODO hien thi dialog
				Log.d(TAG, "Show dialog");
				NMSKTwitterDialog.show(context, activity, this, message);
			}
		}

	}

	public void authorize() {
		progressDialog.setMessage("Initializing ...");
		progressDialog.show();

		new Thread() {
			@Override
			public void run() {
				String authUrl = "";
				int what = 1;

				try {
					ConfigurationBuilder builder = new ConfigurationBuilder();
					builder.setOAuthConsumerKey(consumerKey);
					builder.setOAuthConsumerSecret(secretKey);
					Configuration configuration = builder.build();

					TwitterFactory factory = new TwitterFactory(configuration);
					twitter = factory.getInstance();

					try {
						requestToken = twitter
								.getOAuthRequestToken(callBackURL);
						authUrl = requestToken.getAuthenticationURL();
					} catch (TwitterException e) {
						e.printStackTrace();
					}

					what = 0;
					Log.d(TAG, "Request token url " + authUrl);
				} catch (Exception e) {
					Log.d(TAG, "Failed to get request token");
					e.printStackTrace();
				}
				mHandler.sendMessage(mHandler
						.obtainMessage(what, 1, 0, authUrl));
			}
		}.start();
	}

	public void processToken(String callbackUrl) {
		progressDialog.setMessage("Finalizing ...");
		progressDialog.show();

		final String verifier = getVerifier(callbackUrl);

		new Thread() {
			@Override
			public void run() {
				int what = 1;

				try {
					accessToken = twitter.getOAuthAccessToken(requestToken,
							verifier);
					User user = twitter.verifyCredentials();
					NMSKTwitterSession.getInstance(context).storeAccessToken(
							accessToken, "@" + user.getScreenName());
					what = 0;
				} catch (Exception e) {
					Log.d(TAG, "Error getting access token");
					e.printStackTrace();
				}
				mHandler.sendMessage(mHandler.obtainMessage(what, 2, 0));
			}
		}.start();
	}

	private String getVerifier(String callbackUrl) {
		String verifier = "";

		try {
			URL url = new URL(callbackUrl);
			String query = url.getQuery();

			String array[] = query.split("&");

			for (String parameter : array) {
				String v[] = parameter.split("=");

				if (v[0].equals(oauth.signpost.OAuth.OAUTH_VERIFIER)) {
					verifier = v[1];
					break;
				}
			}
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}

		return verifier;
	}

	private static class MyHandler extends Handler {
		private NMSKTwitterHelper twitterHelper;

		public MyHandler(NMSKTwitterHelper twitterHelper) {
			this.twitterHelper = twitterHelper;
		}

		@Override
		public void handleMessage(Message msg) {
			twitterHelper.progressDialog.dismiss();

			if (msg.what == 1) {
				if (msg.arg1 == 1)
					Log.d(TAG, "Error getting request token");
				else
					Log.d(TAG, "Error getting access token");
			} else if (msg.what == 999) {
				String error = msg.getData().getString("ERROR");
				if (error != null) {
					Toast.makeText(
							twitterHelper.activity.getApplicationContext(),
							error, Toast.LENGTH_SHORT).show();
				} else {
					Toast.makeText(
							twitterHelper.activity.getApplicationContext(),
							twitterHelper.activity
									.getString(R.string.tw_posted),
							Toast.LENGTH_LONG).show();
				}
			} else {
				if (msg.arg1 == 1)
					// show Login Dialog
					NMSKTwitterLoginDialog.show(twitterHelper.context,
							twitterHelper.callBackURL, (String) msg.obj,
							twitterHelper);
				else {
					// TODO
					Log.d(TAG, "Show dialog");
					NMSKTwitterDialog.show(twitterHelper.context,
							twitterHelper.activity, twitterHelper,
							twitterHelper.message);
				}
			}
		}
	};

	public boolean hasAccessToken() {
		return (accessToken == null) ? false : true;
	}

	public void resetAccessToken() {
		if (accessToken != null) {
			NMSKTwitterSession.getInstance(context).resetAccessToken();
			accessToken = null;
		}
	}

	@Override
	public void onComplete(String value) {
		Log.d(TAG, "onComplete");
		processToken(value);
	}

	@Override
	public void onError(String value) {
		Toast.makeText(context, "Twitter connection failed", Toast.LENGTH_LONG)
				.show();
		resetAccessToken();

	}

	@Override
	public void cancel() {
		Log.d(TAG, "cancel");
	}

	@Override
	public void didSharedWithMessage(final NMShareMessage message) {
		// using Twitter api
		if (hasAccessToken()) {
			new Thread(new Runnable() {

				@Override
				public void run() {
					String error = null;
					if (message.getType() == NMShareType.NMShareTypeStory) {
						error = postStatusWithMedia(message.getMessage(),
								new File(message.getPicture()));
					} else {
						error = postStatus(message.getMessage());
					}
					Message message = new Message();
					message.what = 999;
					Bundle b = new Bundle();
					b.putString("ERROR", error);
					message.setData(b);
					mHandler.sendMessage(message);

				}
			}).start();

		}

	}

	public String postStatus(String status) {
		try {
			twitter.updateStatus(status);
			return null;
		} catch (TwitterException e) {
			return e.getErrorMessage();
		}
	}

	public String postStatusWithMedia(String status, File file) {
		try {
			StatusUpdate statusUpdate = new StatusUpdate(status);
			statusUpdate.setMedia(file);
			twitter.updateStatus(statusUpdate);
			return null;
		} catch (TwitterException e) {
			return e.getErrorMessage();
		} catch (Exception e) {
			return e.getMessage();
		}
	}
}
